home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / parser / scanner.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  3.8 KB  |  228 lines

  1. static char *scanner_c = "$Header: /private/postgres/src/parser/RCS/scanner.c,v 1.17 1992/04/09 17:59:12 mer Exp $";
  2.  
  3. #include <ctype.h>
  4.  
  5. #define false 0
  6. #define true !false
  7.  
  8. /*
  9.  *    Support routines for the scanner.
  10.  *    Includes: comment, character constant,
  11.  *    and string constant scanning.
  12.  */
  13.  
  14. /*
  15.  *    Scan PL/1 style comment.
  16.  */
  17. scancmnt()
  18. {
  19.     register int c, trail;
  20.  
  21.     trail = 0;
  22.     for (;;) {
  23.         c = input();
  24.         switch (c) {
  25.         case 0:
  26.             serror("Unterminated comment.");
  27.             return;
  28.         
  29.         case '/':
  30.             if (trail == '*')
  31.                 return;
  32.         }
  33.         trail = c;
  34.     }
  35. }
  36.  
  37. char    delimiter;
  38.  
  39. /*
  40.  *  Scan a character constant into yytext.
  41.  */
  42. scanchar(buf)
  43. char *buf;
  44. {
  45.     delimiter = '\'';
  46.     scancon(buf, 1);
  47. }
  48.  
  49. scanstr(buf, len)
  50. char *buf;
  51. int len;
  52. {
  53.     delimiter = '\"';
  54.     scancon(buf, len);
  55. }
  56. scanspecial(buf, len)
  57. char *buf;
  58. int len;
  59. {
  60.     delimiter = '`';
  61.     scancon(buf, len);
  62. }
  63.  
  64. /*
  65.  * Scan a string.  The leading delimiter (", ') has already been
  66.  * read.  Be sure to gobble up the whole thing, including the
  67.  * trailing delimiter.
  68.  */
  69.  
  70. scancon(buf, len)
  71. char *buf;
  72. int len;
  73. {
  74.     register char *cp = buf;
  75.     register int c, dc, cspec;
  76.     int entering = 1;
  77.  
  78.     cspec = 0;
  79.     while ((c = input()) != delimiter) {
  80.  
  81.         if (cp - buf > len - 1) {
  82.             serror("String/char constant too large");
  83.             cp = buf;
  84.         }
  85.  
  86.         switch (c) {
  87.         default:
  88.             *cp++ = c;
  89.             break;
  90.         case '{':
  91.             /*
  92.              * Right curly brace indicates array constant.
  93.              */
  94.             if (entering && delimiter == '\"')
  95.             {
  96.                 scanarr(buf, len);
  97.                 cp += strlen(buf);
  98.                 cspec = cp - buf - 1;
  99.             }
  100.             else
  101.                 *cp++ = c;
  102.             break;
  103.         case 0:
  104.         case '\n':
  105.             serror("Unterminated char/string constant");
  106.             goto out;
  107.  
  108.         case '\\':
  109.             c = input();
  110.             if (c == '\n')
  111.                 continue;
  112.             /* *cp++ = '\\'; When _should_ this be done? XXX */
  113.             if (isdigit(c)) {
  114.                 dc = 0;
  115.                 while (dc++ < 3 && isdigit(c)) {
  116.                     *cp++ = c;
  117.                     c = input();
  118.                 }
  119.                 unput(c);
  120.                 break;
  121.             }
  122.             if (c != 0) {
  123.                 switch (c) {
  124.                 case 't': c = '\t'; break;
  125.                 case 'n': c = '\n'; break;
  126.                 case 'r': c = '\r'; break;
  127.                 case 'b': c = '\b'; break;
  128.                 case 'f': c = '\f'; break;
  129.                 default: break;
  130.                 }
  131.                 *cp++ = c;
  132.             }
  133.             break;
  134.         }
  135.         entering = 0;
  136.         cspec++;
  137.     }
  138.  
  139. out:
  140.     *cp = 0;
  141.     return(cspec);
  142. }
  143.  
  144. /*
  145.  * Scan input for array_in.  The leading delimiter ({) has already been
  146.  * read.  Be sure to gobble up the whole thing, including the
  147.  * trailing delimiter.
  148.  */
  149.  
  150. scanarr(buf, len)
  151. char *buf;
  152. int len;
  153. {
  154.     register char *cp = buf;
  155.     register int c, c2, dc, cspec, 
  156.              counter;  /* counts matching '{' and '}'.  */
  157.                    /* stop scanning when unmatched '}' */
  158.                    /* is encounterd. */
  159.     int in_string = false;
  160.  
  161.     cspec = 0;
  162.     /*
  163.      * counter counts {'s, so we can do nested arrays properly.
  164.      * It starts from 1 (not zero) because the first thing we encountered
  165.      * was a {.
  166.      */
  167.  
  168.     counter = 1;
  169.  
  170.     *cp++ = '{'; /* array funcs assume that there is a proper nesting */
  171.  
  172.     while (counter != 0) {
  173.         c = input();
  174.         if ( c == '{' && !in_string) counter++;
  175.         if ( c == '}' && !in_string) counter--;
  176.         if (cp - buf > len - 1) {
  177.             serror("String/char constant too large");
  178.             cp = buf;
  179.         }
  180.         switch (c) {
  181.         default:
  182.             *cp++ = c;
  183.             break;
  184.  
  185.         case 0:
  186.         case '\n':
  187.             serror("Unterminated array constant");
  188.             goto out;
  189.  
  190.         case '\\':
  191.             c = input();
  192.             if (c == '\n')
  193.                 continue;
  194.             /* *cp++ = '\\'; When _should_ this be done? XXX */
  195.             if (isdigit(c)) {
  196.                 dc = 0;
  197.                 while (dc++ < 3 && isdigit(c)) {
  198.                     *cp++ = c;
  199.                     c = input();
  200.                 }
  201.                 unput(c);
  202.                 break;
  203.             }
  204.             if (c != 0) {
  205.                 switch (c) {
  206.                 case 't': c = '\t'; break;
  207.                 case 'n': c = '\n'; break;
  208.                 case 'r': c = '\r'; break;
  209.                 case 'b': c = '\b'; break;
  210.                 case 'f': c = '\f'; break;
  211.                 default: *cp++ = '\\'; break;
  212.                 }
  213.                 *cp++ = c;
  214.             }
  215.             break;
  216.         case '\"':
  217.             in_string = !in_string;
  218.             *cp++ = c;
  219.             break;
  220.         }
  221.         cspec++;
  222.     }
  223.  
  224. out:
  225.     *cp = 0;
  226.     return(cspec);
  227. }
  228.